package $2_1oo;

public class PolymorphicFunction {

	public static void main(String[] args) {
		// 多态
		// 在继承关系中，子类如果定义了一个与父类方法签名完全相同的方法，被称为覆写（Override）
		// 多态具有一个非常强大的功能，就是允许添加更多类型的子类实现功能扩展，却不需要修改基于父类的代码。
		// 在必要的情况下，我们可以覆写Object的这几个方法。
		Personi p = new Studenti();
        p.run(); // 应该打印Person.run还是Student.run?

        // 给一个有普通收入、工资收入和享受国务院特殊津贴的小伙伴算税:
        Income[] incomes = new Income[] {
            new Income(3000),
            new Salary(7500),
            new StateCouncilSpecialAllowance(15000)
        };
        System.out.println(totalTax(incomes));
	}
    public static double totalTax(Income... incomes) {
        double total = 0;
        for (Income income: incomes) {
            total = total + income.getTax();
        }
        return total;
    }

}

// 在Person类中，我们定义了run()方法
class Personi {
	
	protected String name;
	
    public void run() {
        System.out.println("Person.run");
    }
    
    // 用final修饰的方法不能被Override
    public final String hello() {
        return "Hello, " + name;
    }
    
    // 显示更有意义的字符串:
    @Override
    public String toString() {
        return "Person:name=" + name;
    }

    // 比较是否相等:
    @Override
    public boolean equals(Object o) {
        // 当且仅当o为Person类型:
        if (o instanceof Personi) {
            Personi p = (Personi) o;
            // 并且name字段相同时，返回true:
            return this.name.equals(p.name);
        }
        return false;
    }

    // 计算hash:
    @Override
    public int hashCode() {
        return this.name.hashCode();
    }
}
// 在子类Student中，覆写这个run()方法
// Override和Overload不同的是，
// 如果方法签名不同，就是Overload，Overload方法是一个新方法；
// 如果方法签名相同，并且返回值也相同，就是Override。
// 加上@Override可以让编译器帮助检查是否进行了正确的覆写。
// 希望进行覆写，但是不小心写错了方法签名，编译器会报错。但是@Override不是必需的。
class Studenti extends Personi {
    @Override
    public void run() {
        System.out.println("Student.run");
    }
}

class Income {
    protected double income;

    public Income(double income) {
        this.income = income;
    }

    public double getTax() {
    	System.out.println(income * 0.1);
        return income * 0.1; // 税率10%
    }
}

class Salary extends Income {
    public Salary(double income) {
        super(income);
    }

    @Override
    public double getTax() {
        if (income <= 5000) {
            return 0;
        }
        System.out.println((income - 5000) * 0.2);
        return (income - 5000) * 0.2;
    }
}

class StateCouncilSpecialAllowance extends Income {
    public StateCouncilSpecialAllowance(double income) {
        super(income);
    }

    @Override
    public double getTax() {
        return 0;
    }
}